package it.fdev.encryptionUtils;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import android.util.Base64;
public class CryptoMan_2 {
public static final String PKCS12_DERIVATION_ALGORITHM = "PBEWITHSHA256AND256BITAES-CBC-BC";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static String DELIMITER = "]";
private static int KEY_LENGTH = 256;
// minimum values recommended by PKCS#5, increase as necessary
private static int ITERATION_COUNT = 1000;
private static final int PKCS5_SALT_LENGTH = 8;
private static SecureRandom random = new SecureRandom();
private static final String PASS = "0qTK0VWXvojSQdX";
private static SecretKey key;
private static SecretKey deriveKey(String password, byte[] salt) {
return CryptoMan_2.deriveKeyPkcs12(salt, password);
}
private static String encrypt(String plaintext, String password) {
byte[] salt = CryptoMan_2.generateSalt();
key = deriveKey(password, salt);
// Log.d(TAG, "Generated key: " + getRawKey());
return CryptoMan_2.encryptPkcs12(plaintext, key, salt);
}
public static String encrypt(String plaintext) {
return encrypt(plaintext, PASS);
}
private static String decrypt(String ciphertext, String password) {
return CryptoMan_2.decryptPkcs12(ciphertext, password);
}
public static String decrypt(String ciphertext) {
return decrypt(ciphertext, PASS);
}
// private static String getRawKey() {
// if (key == null) {
// return null;
// }
// return CryptoMan_2.toHex(key.getEncoded());
// }
private static SecretKey deriveKeyPkcs12(byte[] salt, String password) {
try {
// long start = System.currentTimeMillis();
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PKCS12_DERIVATION_ALGORITHM);
SecretKey result = keyFactory.generateSecret(keySpec);
// long elapsed = System.currentTimeMillis() - start;
// Log.d(TAG, String.format("PKCS#12 key derivation took %d [ms].", elapsed));
return result;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
private static byte[] generateSalt() {
byte[] b = new byte[PKCS5_SALT_LENGTH];
random.nextBytes(b);
return b;
}
private static String encryptPkcs12(String plaintext, SecretKey key, byte[] salt) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
cipher.init(Cipher.ENCRYPT_MODE, key, pbeSpec);
// Log.d(TAG, "Cipher IV: " + toHex(cipher.getIV()));
byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
return String.format("%s%s%s", toBase64(salt), DELIMITER, toBase64(cipherText));
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
// private static String toHex(byte[] bytes) {
// StringBuffer buff = new StringBuffer();
// for (byte b : bytes) {
// buff.append(String.format("%02X", b));
// }
//
// return buff.toString();
// }
private static String toBase64(byte[] bytes) {
return Base64.encodeToString(bytes, Base64.NO_WRAP);
}
private static byte[] fromBase64(String base64) {
return Base64.decode(base64, Base64.NO_WRAP);
}
private static String decryptPkcs12(byte[] cipherBytes, SecretKey key, byte[] salt) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
cipher.init(Cipher.DECRYPT_MODE, key, pbeSpec);
// Log.d(TAG, "Cipher IV: " + toHex(cipher.getIV()));
byte[] plainBytes = cipher.doFinal(cipherBytes);
String plainrStr = new String(plainBytes, "UTF-8");
return plainrStr;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static String decryptPkcs12(String ciphertext, String password) {
String[] fields = ciphertext.split(DELIMITER);
if (fields.length != 2) {
throw new IllegalArgumentException("Invalid encypted text format");
}
byte[] salt = fromBase64(fields[0]);
byte[] cipherBytes = fromBase64(fields[1]);
SecretKey key = deriveKeyPkcs12(salt, password);
return decryptPkcs12(cipherBytes, key, salt);
}
}